package org.jeecg.modules.system.controller;

import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.enums.FileTypeEnum;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.MinioUtil;
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.oss.entity.OssFile;
import org.jeecg.modules.oss.service.IOssFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @Author scott
 * @since 2018-12-20
 */
@Slf4j
@RestController
@RequestMapping("/sys/common")
public class CommonController {

    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    /**
     * 本地：local minio：minio 阿里：alioss
     */
    @Value(value = "${jeecg.uploadType}")
    private String uploadType;
    @Autowired
    private IOssFileService ossFileService;

    /**
     * @Author 政辉
     * @return
     */
    @GetMapping("/403")
    public Result<?> noauth() {
        return Result.error("没有权限，请联系管理员分配权限！");
    }

    /**
     * 文件上传统一方法
     * 
     * @return
     */
    @PostMapping(value = "/uploadLocal")
    public Result<?> uploadLocal(@RequestParam("file") MultipartFile file,
            @RequestParam(value = "fileType", required = false) String fileType,
            @RequestParam(value = "biz", required = false) String bizPath,
            @RequestParam(value = "businessId", required = false) String businessId,
            HttpServletRequest request) throws Exception {
        Result<?> result = new Result<>();
        String savePath = "";
        // 检查文件是否存在
        if (file == null || file.isEmpty()) {
            result.setMessage("文件不能为空");
            result.setSuccess(false);
            return result;
        }

        // LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
        if (oConvertUtils.isNotEmpty(bizPath)) {
            if (bizPath.contains(SymbolConstant.SPOT_SINGLE_SLASH)
                    || bizPath.contains(SymbolConstant.SPOT_DOUBLE_BACKSLASH)) {
                throw new JeecgBootException("上传目录bizPath，格式非法！");
            }
        }

        if (oConvertUtils.isEmpty(bizPath)) {
            if (CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)) {
                // 未指定目录，则用阿里云默认目录 upload
                bizPath = "upload";
                // result.setMessage("使用阿里云文件上传时，必须添加目录！");
                // result.setSuccess(false);
                // return result;
            } else {
                bizPath = "";
            }
        }
        if (CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)) {
            // update-begin-author:liusq date:20221102 for: 过滤上传文件类型
            SsrfFileTypeFilter.checkUploadFileType(file);
            // update-end-author:liusq date:20221102 for: 过滤上传文件类型
            // update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
            savePath = this.uploadLocal(file, bizPath);
            // update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
        } else {
            // update-begin-author:taoyan date:20200814 for:文件上传改造
            // 根据配置文件中的miniourl保存url时只保存相对路径
            if (CommonConstant.UPLOAD_TYPE_MINIO.equals(uploadType)) {
                savePath = CommonUtils.uploadReturnRelativePath(file, bizPath, uploadType);
            } else {
                savePath = CommonUtils.upload(file, bizPath, uploadType);
            }
            // update-end-author:taoyan date:20200814 for:文件上传改造
        }
        if (oConvertUtils.isNotEmpty(savePath)) {
            OssFile ossFile = new OssFile();
            ossFile.setFileName(CommonUtils.getFileName(file.getName()));
            ossFile.setFileType(fileType);
            ossFile.setSuffix(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1));
            ossFile.setUrl(savePath);
            ossFile.setStorageType(uploadType);
            ossFile.setBusinessId(businessId);
            ossFileService.save(ossFile);
        } else {
            result.setMessage("上传失败！");
            result.setSuccess(false);
            return result;
        }
        String url = MinioUtil.getDynamicMinioUrl(request) + savePath;
        return Result.OK(savePath, url);
    }

    /**
     * 本地文件上传
     * 
     * @param mf      文件
     * @param bizPath 自定义路径
     * @return
     */
    private String uploadLocal(MultipartFile mf, String bizPath) {
        try {
            String ctxPath = uploadpath;
            String fileName = null;
            File file = new File(ctxPath + File.separator + bizPath + File.separator);
            if (!file.exists()) {
                // 创建文件根目录
                file.mkdirs();
            }
            // 获取文件名
            String orgName = mf.getOriginalFilename();
            orgName = CommonUtils.getFileName(orgName);
            if (orgName.indexOf(SymbolConstant.SPOT) != -1) {
                fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis()
                        + orgName.substring(orgName.lastIndexOf("."));
            } else {
                fileName = orgName + "_" + System.currentTimeMillis();
            }
            String savePath = file.getPath() + File.separator + fileName;
            File savefile = new File(savePath);
            FileCopyUtils.copy(mf.getBytes(), savefile);
            String dbpath = null;
            if (oConvertUtils.isNotEmpty(bizPath)) {
                dbpath = bizPath + File.separator + fileName;
            } else {
                dbpath = fileName;
            }
            if (dbpath.contains(SymbolConstant.DOUBLE_BACKSLASH)) {
                dbpath = dbpath.replace(SymbolConstant.DOUBLE_BACKSLASH, SymbolConstant.SINGLE_SLASH);
            }
            return dbpath;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }

    // @PostMapping(value = "/upload2")
    // public Result<?> upload2(HttpServletRequest request, HttpServletResponse
    // response) {
    // Result<?> result = new Result<>();
    // try {
    // String ctxPath = uploadpath;
    // String fileName = null;
    // String bizPath = "files";
    // String tempBizPath = request.getParameter("biz");
    // if(oConvertUtils.isNotEmpty(tempBizPath)){
    // bizPath = tempBizPath;
    // }
    // String nowday = new SimpleDateFormat("yyyyMMdd").format(new Date());
    // File file = new File(ctxPath + File.separator + bizPath + File.separator +
    // nowday);
    // if (!file.exists()) {
    // file.mkdirs();// 创建文件根目录
    // }
    // MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)
    // request;
    // MultipartFile mf = multipartRequest.getFile("file");// 获取上传文件对象
    // String orgName = mf.getOriginalFilename();// 获取文件名
    // fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" +
    // System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));
    // String savePath = file.getPath() + File.separator + fileName;
    // File savefile = new File(savePath);
    // FileCopyUtils.copy(mf.getBytes(), savefile);
    // String dbpath = bizPath + File.separator + nowday + File.separator +
    // fileName;
    // if (dbpath.contains("\\")) {
    // dbpath = dbpath.replace("\\", "/");
    // }
    // result.setMessage(dbpath);
    // result.setSuccess(true);
    // } catch (IOException e) {
    // result.setSuccess(false);
    // result.setMessage(e.getMessage());
    // log.error(e.getMessage(), e);
    // }
    // return result;
    // }

    /**
     * 预览图片&下载文件
     * 请求地址：http://localhost:8080/common/static/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
     *
     * @param request
     * @param response
     */
    @GetMapping(value = "/static/**")
    public void view(HttpServletRequest request, HttpServletResponse response) {
        // ISO-8859-1 ==> UTF-8 进行编码转换
        String imgPath = extractPathFromPattern(request);
        if (oConvertUtils.isEmpty(imgPath) || CommonConstant.STRING_NULL.equals(imgPath)) {
            return;
        }
        // 其余处理略
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            imgPath = imgPath.replace("..", "").replace("../", "");
            if (imgPath.endsWith(SymbolConstant.COMMA)) {
                imgPath = imgPath.substring(0, imgPath.length() - 1);
            }
            // update-begin---author:liusq ---date:20230912 for：检查下载文件类型--------------
            SsrfFileTypeFilter.checkDownloadFileType(imgPath);
            // update-end---author:liusq ---date:20230912 for：检查下载文件类型--------------

            String filePath = uploadpath + File.separator + imgPath;
            File file = new File(filePath);
            if (!file.exists()) {
                response.setStatus(404);
                log.error("文件[" + imgPath + "]不存在..");
                return;
                // throw new RuntimeException();
            }
            // 设置强制下载不打开
            response.setContentType("application/force-download");
            response.addHeader("Content-Disposition",
                    "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"), "iso-8859-1"));
            inputStream = new BufferedInputStream(new FileInputStream(filePath));
            outputStream = response.getOutputStream();
            byte[] buf = new byte[1024];
            int len;
            while ((len = inputStream.read(buf)) > 0) {
                outputStream.write(buf, 0, len);
            }
            response.flushBuffer();
        } catch (IOException e) {
            log.error("预览文件失败" + e.getMessage());
            response.setStatus(404);
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }

    }

    // /**
    // * 下载文件
    // *
    // 请求地址：http://localhost:8080/common/download/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
    // *
    // * @param request
    // * @param response
    // * @throws Exception
    // */
    // @GetMapping(value = "/download/**")
    // public void download(HttpServletRequest request, HttpServletResponse
    // response) throws Exception {
    // // ISO-8859-1 ==> UTF-8 进行编码转换
    // String filePath = extractPathFromPattern(request);
    // // 其余处理略
    // InputStream inputStream = null;
    // OutputStream outputStream = null;
    // try {
    // filePath = filePath.replace("..", "");
    // if (filePath.endsWith(",")) {
    // filePath = filePath.substring(0, filePath.length() - 1);
    // }
    // String localPath = uploadpath;
    // String downloadFilePath = localPath + File.separator + filePath;
    // File file = new File(downloadFilePath);
    // if (file.exists()) {
    // response.setContentType("application/force-download");// 设置强制下载不打开          
    //  
    // response.addHeader("Content-Disposition", "attachment;fileName=" + new
    // String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
    // inputStream = new BufferedInputStream(new FileInputStream(file));
    // outputStream = response.getOutputStream();
    // byte[] buf = new byte[1024];
    // int len;
    // while ((len = inputStream.read(buf)) > 0) {
    // outputStream.write(buf, 0, len);
    // }
    // response.flushBuffer();
    // }
    //
    // } catch (Exception e) {
    // log.info("文件下载失败" + e.getMessage());
    // // e.printStackTrace();
    // } finally {
    // if (inputStream != null) {
    // try {
    // inputStream.close();
    // } catch (IOException e) {
    // e.printStackTrace();
    // }
    // }
    // if (outputStream != null) {
    // try {
    // outputStream.close();
    // } catch (IOException e) {
    // e.printStackTrace();
    // }
    // }
    // }
    //
    // }

    /**
     * @功能：pdf预览Iframe
     * @param modelAndView
     * @return
     */
    @RequestMapping("/pdf/pdfPreviewIframe")
    public ModelAndView pdfPreviewIframe(ModelAndView modelAndView) {
        modelAndView.setViewName("pdfPreviewIframe");
        return modelAndView;
    }

    /**
     * 把指定URL后的字符串全部截断当成参数
     * 这么做是为了防止URL中包含中文或者特殊字符（/等）时，匹配不了的问题
     * 
     * @param request
     * @return
     */
    private static String extractPathFromPattern(final HttpServletRequest request) {
        String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
    }

}
